package com.zmj.sy.mom.srv.aps.controller;

import com.zmj.sy.mom.srv.aps.bean.entity.order.Order;
import com.zmj.sy.mom.srv.aps.bean.entity.resource.LogApi;
import com.zmj.sy.mom.srv.aps.bean.entity.third.SinoCamReceiveNestCheck;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseIdReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BasePageResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.BaseResVo;
import com.zmj.sy.mom.srv.aps.bean.vo.base.Result;
import com.zmj.sy.mom.srv.aps.bean.vo.lantek.*;
import com.zmj.sy.mom.srv.aps.bean.vo.mesNest.MesReceiveNestPlateReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.nest.newNest.NestPickingHeader;
import com.zmj.sy.mom.srv.aps.bean.vo.nest.newNest.NestPlateInfo;
import com.zmj.sy.mom.srv.aps.bean.vo.nest.newNest.ReceiveNestPlateReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.sinocam.*;
import com.zmj.sy.mom.srv.aps.bean.vo.texturereplace.TextureReplaceSelectReqVo;
import com.zmj.sy.mom.srv.aps.bean.vo.texturereplace.TextureReplaceSelectResVo;
import com.zmj.sy.mom.srv.aps.lock.BaseRepeatLock;
import com.zmj.sy.mom.srv.aps.mapper.OrderMapper;
import com.zmj.sy.mom.srv.aps.service.HexagonService;
import com.zmj.sy.mom.srv.aps.service.SinoCamService;
import com.zmj.sy.mom.srv.aps.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RequiredArgsConstructor
@Api(tags = "兰特克套料")
@RestController
@RequestMapping("/sinoCam")
public class SinoCamController {

    private final SinoCamService sinoCamService;
    private final HexagonService hexagonService;
    private final LogApiUtils logApiUtils;
    private final OrderMapper orderMapper;
    private final StringRedisTemplate stringRedisTemplate;

    @ApiOperation("推送信息到MES（马凯调用）")
    @PostMapping("/pushMesMK")
    public BaseResVo pushMesMK(@RequestBody BaseIdReqVo reqVo) {
        sinoCamService.pushMesMK(reqVo);
        return BaseResVo.ok();
    }

    @ApiOperation("原材料需求计划")
    @GetMapping("/plateList")
    public BasePageResVo<SinoCamPlateListResVo> plateList(SinoCamPlateListReqVo reqVo) {
        return sinoCamService.plateList(reqVo);
    }

    @ApiOperation("海克斯康-套料")
    @PostMapping("/pushNest")
    public BaseResVo pushNest(@RequestBody SinoCamPushNestReqVo reqVo) {
        hexagonService.pushNest(reqVo);
        return BaseResVo.ok();
    }

    @ApiOperation("推送选择界面")
    @GetMapping("/pushSelect")
    public List<LantekPushSelectListVo> pushSelect(BaseIdReqVo reqVo) {
        List<LantekPushSelectListVo> list = sinoCamService.pushSelect(reqVo);
        return list;
    }

    @ApiOperation("零件推送详情")
    @GetMapping("/pushPartInfoDetail")
    public BasePageResVo<PushPartInfoResVo> pushPartInfoDetail(PushStateReqVo reqVo) {
        return sinoCamService.pushPartInfoDetail(reqVo);
    }

    @ApiOperation("包次推送详情")
    @GetMapping("pushSeqDetail")
    public Result<List<PushSeqDetailResVo>> pushSeqDetail(PushStateReqVo reqVo) {
        List<PushSeqDetailResVo> list = sinoCamService.pushSeqDetail(reqVo);
        return Result.success(list);
    }

    @ApiOperation("查询零件信息")
    @GetMapping("/getPartInfo")
    public Result<List<LantekPartInfoResVo>> getPartInfo(LantekPartInfoReqVo reqVo) {
        List<LantekPartInfoResVo> list = sinoCamService.getPartInfo(reqVo);
        return Result.success(list);
    }

    @ApiOperation("查询套料计划")
    @GetMapping("/getPlan")
    public Result<List<LantekNestPlanResVo>> getPlan(LantekNestPlanReqVo reqVo) {
        List<LantekNestPlanResVo> list = sinoCamService.getPlan(reqVo);
        return Result.success(list);
    }

    @ApiOperation("图纸解析零件信息")
    @GetMapping("/drawingAnalysis")
    public Result<LantekDrawingInfoResVo> drawingAnalysis(Integer orderPartId) throws Exception {
        LantekDrawingInfoResVo vo = sinoCamService.drawingAnalysis(orderPartId);
        return Result.success(vo);
    }

    @ApiOperation("图纸转换-根据DXF转换PNG")
    @GetMapping("/exchangePNG")
    public Result<?> exchangePNG(Integer orderPartId) throws Exception {
        sinoCamService.exchangePNG(orderPartId);
        return Result.success("success！");
    }

    @ApiOperation("图纸转换-根据DXF转换PDF")
    @GetMapping("/exchangePDF")
    public Result<?> exchangePDF(Integer orderPartId) throws Exception {
        sinoCamService.exchangePDF(orderPartId);
        return Result.success("success！");
    }

    @ApiOperation("材质替换-下拉框")
    @GetMapping("/textureReplace")
    public Result<List<String>> textureSelect(String texture) {
        List<String> list = sinoCamService.textureReplace(texture);
        return Result.success(list);
    }

    @ApiOperation("材质以高代低-查询")
    @GetMapping("/textureReplaceSelect")
    public Result<List<TextureReplaceSelectResVo>> textureReplaceSelect(TextureReplaceSelectReqVo reqVo) {
        List<TextureReplaceSelectResVo> list = sinoCamService.textureReplaceSelect(reqVo);
        return Result.success(list);
    }

    @ApiOperation("查询钢板接收状态")
    @GetMapping("/checkPlateReceive")
    public boolean checkPlateReceive(String nestId) {
        return sinoCamService.checkPlateReceive(nestId);
    }

    @ApiOperation("拆分PZ工序数量大于10的计划")
    @PostMapping("/splitPlan")
    public BaseResVo splitPlan() {
        return sinoCamService.splitPlan();
    }

    @ApiOperation("填补OrderPart表DXF空缺问题")
    @PostMapping("/fillDxf")
    public BaseResVo fillDxf() {
        sinoCamService.fillDxf();
        return BaseResVo.ok();
    }

    @ApiOperation("清空套料结果（套料图号——MES）")
    @PostMapping("/clearNestResultInfo")
    public BaseResVo clearNestResultInfo(@RequestBody String nestId) {
        sinoCamService.clearNestResultInfo(nestId);
        return BaseResVo.ok();
    }

    @ApiOperation("清空套料结果（钢板号——MES）")
    @PostMapping("/clearNestResultInfoPlate")
    public BaseResVo clearNestResultInfoPlate(@RequestBody String plateCode) {
        sinoCamService.clearNestResultInfoPlate(plateCode);
        return BaseResVo.ok();
    }

    @ApiOperation("清空套料结果（领料单号——MES）")
    @PostMapping("/clearNestResultInfoNew")
    public BaseResVo clearNestResultInfoNew(@RequestBody NestPickingHeader reqVo) {
        sinoCamService.clearNestResultInfoNew(reqVo);
        return BaseResVo.ok();
    }

    @ApiOperation("清空套料结果（领料单号——MES——测试）")
    @PostMapping("/clearNestResultInfoTest")
    public BaseResVo clearNestResultInfoTest(@RequestBody String plateCode) {
        NestPickingHeader reqVo = new NestPickingHeader();
        NestPlateInfo vo = new NestPlateInfo();
        vo.setMaterialId(plateCode);
        List<NestPlateInfo> list = new ArrayList<>();
        list.add(vo);
        reqVo.setNestPlateInfoList(list);
        sinoCamService.clearNestResultInfoNew(reqVo);
        return BaseResVo.ok();
    }

    @ApiOperation("检查套料结果接收情况（钢板号——MES）")
    @PostMapping("/checkNestResult")
    public BaseResVo checkNestResult(@RequestBody String plateCode) {
        String userCode = SySecurityUtils.getUserCode();
        sinoCamService.checkNestResult(plateCode, userCode);
        return BaseResVo.ok();
    }

    @ApiOperation("丢失钢板找回")
    @PostMapping("/catchLostPlate")
    public BaseResVo catchLostPlate(@RequestBody SinoCamCatchLostPlateReqVo reqVo) {
        if ("032240".equals(reqVo.getPassword())) {
            sinoCamService.catchLostPlate(reqVo);
        } else {
            throw SyExceptionUtils.e("密码错误！");
        }
        return BaseResVo.ok();
    }

    @ApiOperation("用零件图号定时查询MES返回零件图纸")
    @GetMapping("getPngPlmId")
    public BaseResVo getPngPlmId(String plmId) throws IOException {
        sinoCamService.getPngPlmId(plmId);
        return BaseResVo.ok();
    }

    @ApiOperation("查找未进入APS的钢板列表")
    @PostMapping("/checkPlateNotAps")
    public List<String> checkPlateNotAps(@RequestBody List<String> list) {
        return sinoCamService.checkPlateNotAps(list);
    }

//    @ApiOperation("修改套料结果请求")
//    @GetMapping("/requestChangeNestInfo")
//    public BaseResVo requestChangeNestInfo() {
//        return sinoCamService.requestChangeNestInfo();
//    }

//    @ApiOperation("接收修改后的套料结果")
//    @PostMapping("/receiveMesAgain")
//    public BaseResVo receiveMesAgain() {
//        return sinoCamService.receiveMesAgain();
//    }

    @ApiOperation("接收MES的套料结果")
    @PostMapping("/receiveMesParts")
    public BaseResVo receiveMesParts(@RequestBody MesReceiveNestPlateReqVo reqVo) {
        sinoCamService.receiveMesParts(reqVo);
        return BaseResVo.ok();
    }

    @ApiOperation("获取APS近期钢板数据，与MES进行比对")
    @PostMapping("/fixChangeNestInfo")
    public List<String> fixChangeNestInfo(@RequestBody List<String> list) {
        return sinoCamService.fixChangeNestInfo(list);
    }

    @ApiOperation("Stream去重测试")
    @PostMapping("/disListStream")
    public List<SinoCamReceiveNestCheck> disListStream() {
        return sinoCamService.disListStream();
    }

    @GetMapping("/excel")
    public ResponseEntity<byte[]> excel(Integer orderId) throws IOException {
        Order order = orderMapper.selectById(orderId);
        try(Workbook workbook = sinoCamService.excel(orderId)) {
            String fileName = order.getConstructNo() + "-" + order.getMaterName() + ".xlsx";
            String fileNameEncoded = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            workbook.write(bytes);
            HttpHeaders headers = new HttpHeaders();
            headers.setContentDisposition(ContentDisposition.builder("attachment").filename(fileNameEncoded).build());
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            return new ResponseEntity<>(bytes.toByteArray(), headers, HttpStatus.OK);
        }
    }

    @SneakyThrows
    @ControllerAspectIgnore
    @ApiOperation("仅接收MES套料结果的零件信息")
    @PostMapping("/receiveMesPartOnly")
    public BaseResVo receiveMesPartOnly(@RequestBody MesReceiveNestPlateReqVo reqVo) {
        sinoCamService.receiveMesPartOnly(reqVo);
        return BaseResVo.ok();
    }

    @ApiOperation("手动修改钢板套料锁定状态——新")
    @PostMapping("/updatePlateNestStatus")
    @BaseRepeatLock(lockKey = "#reqVo.plateCode", lockTime = 10)
    public BaseResVo updatePlateNestStatusNew(@RequestBody SinocamUpdatePlateNestStatusReqVo reqVo) {
        sinoCamService.updatePlateNestStatusNew(reqVo.getPlateCode(), true);
        return BaseResVo.ok();
    }

    @SneakyThrows
    @ControllerAspectIgnore
    @ApiOperation("获取 MES 套料结果——新")
    @PostMapping("/receiveMesNew")
    public BaseResVo receiveMesNew(@RequestBody ReceiveNestPlateReqVo reqVo) {
        log.info("接收套料结果:{}", reqVo.toString());
        LogApi logApi = logApiUtils.getReceiveLog("MES套料", "接收套料结果", "/sinoCam/receiveMesNew");
        // JSON转换
        String s = JsonUtils.toJsonString(reqVo);
        log.info("接受MES套料结果:{}", s);
        Map<String, String> resVo = new HashMap<>();
        try {
            logApiUtils.setReqStr(logApi, s);
            sinoCamService.receiveMesNew(reqVo);
            String remark = "套料图号：" + reqVo.getNestId();
            logApiUtils.successAndSave(logApi, resVo, remark);
        } catch (Exception e) {
            e.printStackTrace();
            logApiUtils.errorAndSave(logApi, resVo, e.getMessage());
            return BaseResVo.fail(e.getMessage());
        }
        return BaseResVo.ok();
    }

    @SneakyThrows
    @ControllerAspectIgnore
    @ApiOperation("获取 MES 套料结果——新——测试")
    @PostMapping("/receiveMesNewTest")
    public BaseResVo receiveMesNewTest() {

        sinoCamService.receiveNestNewTest();

        return BaseResVo.ok();
    }

    @ApiOperation("判断钢板是否被修改过")
    @GetMapping("/checkPlateChange")
    public List<String> checkPlateChange(String plates) {
        return sinoCamService.checkPlateChange(plates);
    }

    @ApiModelProperty("获取保存的套料图号")
    @PostMapping("/receiveNestIdInfo")
    public BaseResVo receiveNestIdInfo(@RequestBody SinoCamNestIdReqVo reqVo) {
        sinoCamService.receiveNestIdInfo(reqVo);
        return BaseResVo.ok();
    }

    /*@ApiOperation("测试Redis锁定与解锁")
    @PostMapping("/testRedisLock")
    public void testRedisLock() {

        ValueOperations<String, String> valOperation = stringRedisTemplate.opsForValue();
        String s1 = valOperation.get("nest");
        System.out.println(s1);

        // 布尔值：true指 setIfAbsent 方法成功执行，由该方法进行上锁成功；false指方法未成功执行，redis锁由其他方法进行锁定，执行休眠或直接返回
        Boolean nest = valOperation.setIfAbsent("nest", "1");
        System.out.println(nest);

        String s2 = valOperation.get("nest");
        System.out.println(s2);

        stringRedisTemplate.delete("nest");
        String s3 = valOperation.get("nest");
        System.out.println(s3);

        valOperation.set("nest", "1");
        String s4 = valOperation.get("nest");
        System.out.println(s4);

    }

    @ApiOperation("测试Redis锁定与解锁")
    @PostMapping("/testUnlock")
    public void testUnlock() {

        stringRedisTemplate.delete("nest");

    }*/

    @ApiOperation("补充计划路径")
    @PostMapping("/addPlanPath")
    public BaseResVo addPlanPath(@RequestBody BaseIdReqVo reqVo) {
        sinoCamService.addPlanPath(reqVo);
        return BaseResVo.ok();
    }

    @ApiOperation("检验套料是否存在")
    @PostMapping("/checkNestExist")
    public BaseResVo checkNestExist(@RequestBody BaseIdReqVo reqVo) {
        sinoCamService.checkNestExist(reqVo);
        return BaseResVo.ok();
    }

}
